package com.lazy.tcp;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;


public class TelnetClient {
    private static Logger logger = Logger.getLogger("TelnetClient");

    protected final String host;
    protected final int port;
    
    protected ClientBootstrap bootstrap = null;

    
    /** 用户传入的channelHandler */
    protected ChannelHandler myHandler = null;

    public TelnetClient(String host, int port, ChannelHandler myHandler) {
        this.host = host;
        this.port = port;
        // this.protocolData = protocolData;
        this.myHandler = myHandler;

        // Configure the client. using FixedThreadPool to avoid too many thread
        bootstrap = new ClientBootstrap(
        // new NioClientSocketChannelFactory(
        // Executors.newCachedThreadPool(),
        // Executors.newCachedThreadPool()));
                new NioClientSocketChannelFactory(
                        Executors.newFixedThreadPool(500),
                        Executors.newFixedThreadPool(500)));

        // Configure the pipeline factory.
        bootstrap.setPipelineFactory(new TelnetClientPipelineFactory(
                myHandler));

    }

    /**
     * 尝试和服务端建立连接，成功 返回Channel, 失败 返回 null
     * @return
     * @throws IOException
     */
    public Channel connect() throws IOException {
        // close if bootstrap is not null before connect
        // close();


        // Start the connection attempt.
        ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));

        // Wait until the connection attempt succeeds or fails.
        Channel channel = future.awaitUninterruptibly().getChannel();

        if (!future.isSuccess()) {
            future.getCause().printStackTrace();
            // bootstrap.releaseExternalResources();
            logger.error("无法链接到" + host+ ":" + port);
            return null;
        }
        return channel;
    }
    
    /**
     * close the connected channel
     * @param channel
     */
    public void disconnect(Channel channel) {
        if (channel != null) {
            // Close the connection.  Make sure the close operation ends because
            // all I/O operations are asynchronous in Netty.
            channel.close().awaitUninterruptibly();
        }
    }

    public ChannelFuture post(Channel channel, String content) {

        ChannelFuture lastWriteFuture = null;
        if (content != null) {
            lastWriteFuture = channel.write(content+"\r\n");

        }

        return lastWriteFuture;
    }
    
    public void close() {
        if (bootstrap != null) {
            // Shut down all thread pools to exit.
            bootstrap.releaseExternalResources();
        }
    }

    public static void main(String[] args) throws Exception {
        // Print usage if no argument is specified.
//        if (args.length != 2) {
//            System.err.println(
//                    "Usage: " + TcpNettyClient.class.getSimpleName() +
//                    " <host> <port>");
//            return;
//        }
//
//        // Parse options.
//        String host = args[0];
//        int port = Integer.parseInt(args[1]);
//      String host = "localhost";
        String host = "192.168.1.178";
        int port = 9102;
        
        TelnetClientHandler myHandler = new TelnetClientHandler();

        // ProtocolRequest content = new ProtocolRequest();
        // content.setCmd("realTimeTrackSeg");
        String content = "test";

        // TODO: 应该是建立连接后， 单独一个函数去发送数据
        TelnetClient client = new TelnetClient(host, port, myHandler);
        Channel channel = client.connect();
        if (channel != null) {
            ChannelFuture lastWriteFuture = client.post(channel, content);
            // Wait until all messages are flushed before closing the channel.
            if (lastWriteFuture != null) {
                lastWriteFuture.awaitUninterruptibly();
            }
            
            Thread.sleep(1000); // wait ret value
            client.disconnect(channel);
        }
        client.close();
    }
}
